package com.zusmart.core.config.support;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.zusmart.base.util.GenericUtils;
import com.zusmart.core.config.ConfigData;
import com.zusmart.core.config.ConfigDataType;
import com.zusmart.core.config.ConfigName;
import com.zusmart.core.config.data.ConfigDataConverterForBigDecimal;
import com.zusmart.core.config.data.ConfigDataConverterForBoolean;
import com.zusmart.core.config.data.ConfigDataConverterForClass;
import com.zusmart.core.config.data.ConfigDataConverterForDate;
import com.zusmart.core.config.data.ConfigDataConverterForDouble;
import com.zusmart.core.config.data.ConfigDataConverterForFloat;
import com.zusmart.core.config.data.ConfigDataConverterForInteger;
import com.zusmart.core.config.data.ConfigDataConverterForLong;
import com.zusmart.core.config.data.ConfigDataConverterForShort;
import com.zusmart.core.config.data.ConfigDataConverterForString;
import com.zusmart.core.config.source.ConfigSourceConverterForProperties;
import com.zusmart.core.config.source.ConfigSourceConverterForXml;
import com.zusmart.core.config.source.ConfigSourceForEnvironment;
import com.zusmart.core.config.source.ConfigSourceForSystem;

public class DefaultConfigSourceManager extends AbstractConfigSourceManager {

	private Map<ConfigName, ConfigData<?>> caches = new ConcurrentHashMap<ConfigName, ConfigData<?>>();

	public DefaultConfigSourceManager() {
		this.attachConfigDataConverter(new ConfigDataConverterForBigDecimal());
		this.attachConfigDataConverter(new ConfigDataConverterForBoolean());
		this.attachConfigDataConverter(new ConfigDataConverterForClass());
		this.attachConfigDataConverter(new ConfigDataConverterForDate());
		this.attachConfigDataConverter(new ConfigDataConverterForDouble());
		this.attachConfigDataConverter(new ConfigDataConverterForFloat());
		this.attachConfigDataConverter(new ConfigDataConverterForInteger());
		this.attachConfigDataConverter(new ConfigDataConverterForLong());
		this.attachConfigDataConverter(new ConfigDataConverterForShort());
		this.attachConfigDataConverter(new ConfigDataConverterForString());

		this.attachConfigSourceConverter(new ConfigSourceConverterForProperties());
		this.attachConfigSourceConverter(new ConfigSourceConverterForXml());

		this.attachConfigSource(new ConfigSourceForEnvironment());
		this.attachConfigSource(new ConfigSourceForSystem());
	}

	@Override
	protected ConfigName createConfigName(String configName) throws Exception {
		return new DefaultConfigName(configName);
	}

	@Override
	protected <T> ConfigData<T> createConfigData(ConfigName configName, T configData, ConfigDataType configType) {
		if (null != configName && this.caches.containsKey(configName)) {
			return GenericUtils.parse(this.caches.get(configName));
		}
		ConfigData<T> configDataObject = super.createConfigData(configName, configData, configType);
		if (null != configDataObject && configDataObject.isDefinition()) {
			this.caches.put(configName, configDataObject);
		}
		return configDataObject;
	}

}